package org.easytouseit.websocket.handler;

import com.fasterxml.jackson.core.type.TypeReference;
import org.easytouseit.websocket.model.WsParam;
import org.easytouseit.websocket.model.WsResponse;
import org.easytouseit.websocket.utils.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author guojm
 * @version V1.0
 * @date 2019-01-09 上午 10:21
 */
@Component
public class SocketHandler implements WebSocketHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //在线用户列表
    private static final Map<String, WebSocketSession> users;
    static {
      users = new HashMap<>();
    }
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        logger.info("Connected ... " + webSocketSession.getId());
        String ID = webSocketSession.getUri().toString().split("ID=")[1];
        logger.info(ID);
        if (ID != null) {
            users.put(ID, webSocketSession);
            WsResponse<String> response = new WsResponse<>();
            response.setResult("hello："+getClientId(webSocketSession)+",成功建立socket连接");
            webSocketSession.sendMessage(new TextMessage(JacksonUtil.bean2Json(response)));
            logger.info(ID);
        }
        System.out.println("当前在线人数："+users.size());
    }

    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        logger.info("handleTextMessage start");
        // 将消息进行转化，因为是消息是json数据，可能里面包含了发送给某个人的信息，所以需要用json相关的工具类处理之后再封装成TextMessage，
        // 我这儿并没有做处理，消息的封装格式一般有{from:xxxx,to:xxxxx,msg:xxxxx}，来自哪里，发送给谁，什么消息等等
        String msg = (String)webSocketMessage.getPayload();
        logger.info("收到来自：{}，的信息：{} ",getClientId(webSocketSession), msg);
        WsParam<String> wsParam = JacksonUtil.json2Bean(msg, new TypeReference<WsParam<String>>(){});
        if ("list".equals(wsParam.getMethod())) {
            logger.info("call list method...");
            WsResponse<String> response = new WsResponse<>();
            response.setResult("hello："+getClientId(webSocketSession)+",msg"+wsParam.getParam());
            sendMessageToUser(webSocketSession, new TextMessage(JacksonUtil.bean2Json(response)));
        }
        logger.info("handleTextMessage end");
    }

    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        if (webSocketSession.isOpen()) {
            webSocketSession.close();
        }
        System.out.println("连接出错");
        users.remove(getClientId(webSocketSession));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        if (webSocketSession.isOpen()) {
            webSocketSession.close();
        }
        users.remove(getClientId(webSocketSession));
        logger.info(String.format("Session %s closed because of %s", webSocketSession.getId(), closeStatus.getReason()));
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    /**
     * 获取用户标识
     * @param session
     * @return
     */
    private String getClientId(WebSocketSession session) {
        try {
            String clientId = (String) session.getAttributes().get("WEBSOCKET_USERID");
            return clientId;
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 给所有的用户发送消息
     */
    public void sendMessagesToUsers(TextMessage message) {
        WebSocketSession session = null;
        for (String userId : users.keySet()) {
            try {
                session =users.get(userId);
                if (session.isOpen()) {
                    session.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送消息给指定的用户
     */
    private void sendMessageToUser(WebSocketSession user, TextMessage message) {
        try {
            // 在线就发送
            if (user.isOpen()) {
                user.sendMessage(message);
            }
        } catch (IOException e) {
            logger.error("发送消息给指定的用户出错", e);
        }
    }
}
